
#include "cl_base_FeatureAnalysis.h"

// [*] CFeatureStructureTree

CFeatureStructureTree::CFeatureStructureTree()
{
	Clear();
}

void CFeatureStructureTree::Clear()
{
	Root = -1;
	NodeAmount = LayerAmount = 0;
	NodeList.DeepClear();
	FeatureDimension = 0;
}

void CFeatureStructureTree::myInit(string strFN_FeatureStructureTree)
{
	ifstream inFile(strFN_FeatureStructureTree.c_str());

	this->Clear();
	CNode& RootNode = this->MakeTree(-1, inFile);
	this->Root = RootNode.SelfNodeIndex;
	this->FeatureDimension = RootNode.FeatureSize_AllGroup;

	inFile.clear();
	inFile.close();


}

CFeatureStructureTree::CNode& CFeatureStructureTree::MakeTree(int ParentIndex, istream& inFile)
{
	int ac, i;

	int MyNodeIndex = MakeNode(ParentIndex).SelfNodeIndex;
	if (ParentIndex < 0) NodeList.pElement[MyNodeIndex].FeatureStartOffSetInGroup = 0;

	inFile>>NodeList.pElement[MyNodeIndex].FeatureGroupAmount;
	inFile>>ac;
	for ( i = 0; i < ac; ++i )
	{
		CNode& ChildNode = MakeTree(NodeList.pElement[MyNodeIndex].SelfNodeIndex, inFile);
		ChildNode.FeatureStartOffSetInGroup = NodeList.pElement[MyNodeIndex].FeatureSize_SingleGroup;
		NodeList.pElement[MyNodeIndex].FeatureSize_SingleGroup += ChildNode.FeatureSize_AllGroup;
	}
	if (ac == 0)
		NodeList.pElement[MyNodeIndex].FeatureSize_SingleGroup = 1;
	NodeList.pElement[MyNodeIndex].FeatureSize_AllGroup = NodeList.pElement[MyNodeIndex].FeatureSize_SingleGroup * NodeList.pElement[MyNodeIndex].FeatureGroupAmount;
	return NodeList.pElement[MyNodeIndex];
}

CFeatureStructureTree::CNode& CFeatureStructureTree::MakeNode(int ParentNodeIndex)
{
	CNode tNode;

	tNode.FeatureGroupAmount = 0;
	tNode.FeatureSize_AllGroup = 0;
	tNode.FeatureSize_SingleGroup = 0;
	tNode.FeatureStartOffSetInGroup = -1;

	tNode.SelfNodeIndex = this->NodeAmount;
	tNode.ParentNodeIndex = ParentNodeIndex;
	tNode.ChildrenAmount = 0;
	tNode.ChildrenNodeIndexList.DeepClear();
	if (ParentNodeIndex < 0)
	{
		tNode.LayerIndex = 0;
		tNode.BrotherIndex = 0;
	}
	else
	{
		CNode& ParentNode = NodeList.pElement[ParentNodeIndex];
		tNode.LayerIndex = ParentNode.LayerIndex + 1;
		tNode.BrotherIndex = ParentNode.ChildrenAmount++;
		ParentNode.ChildrenNodeIndexList.PushBack(tNode.SelfNodeIndex);
	}

	this->NodeList.PushBack(tNode);
	if (tNode.LayerIndex >= LayerAmount) ++LayerAmount;
	return this->NodeList.pElement[this->NodeAmount++];
}

void CFeatureStructureTree::SelectFeature(CSelectedFeature& DstDimension, int FeatureIndex) const
{
	if (FeatureIndex<0 || FeatureIndex>=this->FeatureDimension) return;

	DstDimension.FeatureIndex = FeatureIndex;
	DstDimension.RealDepth = 0;
	DstDimension.List_PerLayer_BrotherIndex.Clear();
	DstDimension.List_PerLayer_GroupIndex.Clear();
	DstDimension.List_PerLayer_NodeIndex.Clear();
	int iNode, i;
	const int* qi;
	for ( iNode = this->Root; ; )
	{
		CNode& tNode = this->NodeList.pElement[iNode];
		++DstDimension.RealDepth;
		DstDimension.List_PerLayer_NodeIndex.PushBack(tNode.SelfNodeIndex);
		DstDimension.List_PerLayer_BrotherIndex.PushBack(tNode.BrotherIndex);
		DstDimension.List_PerLayer_GroupIndex.PushBack(FeatureIndex / tNode.FeatureSize_SingleGroup);
		FeatureIndex %= tNode.FeatureSize_SingleGroup;

		if (tNode.ChildrenAmount == 0) break;

		qi = tNode.ChildrenNodeIndexList.pElement + 1;
		for ( i = 0; i < tNode.ChildrenAmount - 1; ++i, ++qi )
		{
			if (FeatureIndex < this->NodeList.pElement[*qi].FeatureStartOffSetInGroup) break;
		}
		qi = tNode.ChildrenNodeIndexList.pElement + i;
		iNode = *qi;
		FeatureIndex -= this->NodeList.pElement[*qi].FeatureStartOffSetInGroup;
	}
	
	DstDimension.List_PerLayer_BrotherIndex.Resize(LayerAmount, -1);
	DstDimension.List_PerLayer_GroupIndex.Resize(LayerAmount, -1);
	DstDimension.List_PerLayer_NodeIndex.Resize(LayerAmount, -1);
}

